import ddf.minim.*;
import ddf.minim.signals.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;

import processing.opengl.*;

//required imports for tacTile

import processing.net.*;
import tacTile.net.*;

TouchAPI tacTile;

int dataPort = 7100;
int msgPort = 7340;

//boolean to determine which Touch Server connected to.
boolean connectToTacTile = true;

//Names of machines you might use
String localMachine = "asdf";
String tacTileMachine = "tactile.evl.uic.edu";

int currentPhase, currentTime, ship1Life, attackRadius = 125;
Image logo;
boolean decreasing = true;
Ninja ninja1, ninja2, ninja3, ninja4;
Ninja ninjas[];
AIDirector ai;
PImage landBackground;
BackgroundSpanner backgrounds;

void setup() {
  if ( connectToTacTile ){
    size( screen.width, screen.height, OPENGL );
    tacTile = new TouchAPI( this, dataPort, msgPort, tacTileMachine);
  } 
  else {
    size( screen.width, screen.height, OPENGL );
    tacTile = new TouchAPI( this, dataPort, msgPort, localMachine);
  }

  SoundEffects backgroundMusic = new SoundEffects(this, "l4d2_c4_pc.mp3", 0);
  backgroundMusic.start();
  /*
   * change the name of the image to the actual logo name
   */
  logo = new Image(loadImage("logo.png"), new PVector(width/2, height/2), 0, 400, 2);
  currentPhase = 0;
  ship1Life = 500;
  PImage stillNinjas[] = {
    loadImage("stillninja1.png"), loadImage("stillninja2.png")  };
  PImage movingNinjas[] = {
    loadImage("runningninja1.png"),loadImage("runningninja2.png")  }; 
  PImage swingingSword[] = {
    loadImage("swinging1.png"), loadImage("swinging2.png"), loadImage("swinging3.png")  };
  landBackground = loadImage("landBackground.png");
  PImage backgroundImages[] = {
    landBackground, landBackground, landBackground, landBackground, landBackground, landBackground, landBackground, landBackground, landBackground  };
  backgrounds = new BackgroundSpanner(backgroundImages, width/2.0, height/2.0);
  ninja1 = new Ninja(stillNinjas, movingNinjas, swingingSword, 200, 10, new PVector(width/2.0, 300), 75, attackRadius);
  ninja2 = new Ninja(stillNinjas, movingNinjas, swingingSword, 200, 10, new PVector(width/2.0 + 300, 600), 75, attackRadius);
  ninja2.setCurrentAngle(PI/2);
  ninja3 = new Ninja(stillNinjas, movingNinjas, swingingSword, 200, 10, new PVector(width/2.0 - 300, 600), 75, attackRadius);
  ninja3.setCurrentAngle(3*PI/2);
  ninja4 = new Ninja(stillNinjas, movingNinjas, swingingSword, 200, 10, new PVector(width/2.0, 900), 75, attackRadius);
  ninja4.setCurrentAngle(PI);
  Ninja ninjastemp[] = {
    ninja1, ninja2, ninja3, ninja4  };
  ninjas = ninjastemp;
  ai = new AIDirector();
  imageMode(CENTER);
}

void draw(){
  tacTile.process();

  //Gives you expired touches. Alternate method name: getExpiredTouches()
  ArrayList newUp = tacTile.getTouchesUp();         
  //gives you new touches. Alternate method name: getNewTouches()
  ArrayList newDown = tacTile.getTouchesDown();
  //gives you touches that have moved. Alternate method name: getTouchesMoved()
  ArrayList newMoved = tacTile.getMovedTouches();  

  currentTime = millis();

  switch(currentPhase){
  case 0: 
    showIntro(); 
    break;// shows intro logo splash screen
  case 1: 
    showMainScreen(); 
    break;
  case 2: 
    level1(); 
    break;
  }

  if( !newUp.isEmpty() ){
    for(int i = 0; i < newUp.size(); i++){
      Touches touch = ((Touches) newUp.get(i));
      checkIfTouchReleaseIsValid(touch.getFinger());
    } 
  }

  if( !newDown.isEmpty() ){
    float bugx, bugy, xTouch, yTouch;
    for(int j = 0; j < newDown.size(); j++){
      Touches touch = ((Touches) newDown.get(j));
      xTouch = touch.getXPos()*width;
      yTouch = height - touch.getYPos() * height;
      checkIfTouchIsInRange(xTouch, yTouch, touch.getFinger());        
    }
  }

  if( !newMoved.isEmpty() ){
    for(int i = 0; i < newMoved.size(); i++){
      Touches t = ((Touches) newMoved.get(i));
    } 
  }   


}

void showIntro(){
  background(0);
  logo.drawImageWithFadeInTint(currentTime);
  if(logo.hasTimeExpired() == true){
    currentPhase++;
  }
}

void showMainScreen(){
  currentPhase++;
}

void level1(){
  backgrounds.display();
  ai.run();
  ai.displayDeadZombies(currentTime);
  ai.displayZombies(currentTime);
  for(int i = 0; i < ninjas.length; i++){
    if(ninjas[i].isMoving()){
      ninjas[i].moveToAreaThroughAnimation(currentTime); 
    } 
    else if(ninjas[i].isSwinging()){
      ninjas[i].swingSword(currentTime);
      ai.checkIfHit(ninjas[i].currentAngle, attackRadius, ninjas[i].currentLocation);
    } 
    else {
      ninjas[i].update(currentTime); 
    }
  }
}

void checkIfTouchIsInRange(float xOrigin, float yOrigin, int fingerId){
  PVector origin = new PVector(xOrigin, yOrigin);
  for(int i = 0; i < ninjas.length; i++){
    if(ninjas[i].isPointInRange(origin)){
      ninjas[i].setFingerId(fingerId);
      ninjas[i].setVelocity(origin);
      break;
    } 
    else if(ninjas[i].isAttackPointInRange(origin)){
      ninjas[i].startSwing(currentTime);
      break; 
    }
  }  
}

void checkIfTouchReleaseIsValid(int fingerId){
  for(int i = 0; i < ninjas.length; i++){
    if(ninjas[i].getFingerId() == fingerId){
      ninjas[i].isMoving = false; 
    }   
  }  
}

void setMovingId(float x, float y, int id){
  if(x < 50){ 
    if(y < 50){
      backgrounds.moveLocation(1, 1, id);
    } 
    else if(y > height - 50) {
      backgrounds.moveLocation(1, -1, id);
    }
  } 
  else if(x > width - 50){
    if(y < 50){
      backgrounds.moveLocation(-1, 1, id);
    } 
    else if(y > height - 50) {
      backgrounds.moveLocation(-1, -1, id);
    } 
  }
}

void checkIfGameShouldMove(int id){
  if(backgrounds.fingerId == id){
    backgrounds.continueToMove();
  } 
}

void checkIfGameShouldStopMoving(int id){
  if(backgrounds.fingerId == id){
    backgrounds.fingerId = -1; 
  }
}

void mousePressed(){
  checkIfTouchIsInRange(mouseX, mouseY, 1);
  setMovingId(mouseX, mouseY, 1);
}

void mouseDragged(){
}

void mouseReleased(){
  for(int i = 0; i < ninjas.length; i++){
    ninjas[i].isMoving = false;    
  }  
  checkIfGameShouldStopMoving(1);
}




